﻿/* ============================================================================
(c) Copyright 2012 Hewlett-Packard Development Company, L.P.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights to
use, copy, modify, merge,publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
============================================================================ */
using System;
using HPCloud.Objects.Domain.Admin;
using HPCloud.Objects.DataAccess.Security;
using HPCloud.Common.Properties;
using System.Xml.Linq;
using System.Security;
using System.Xml.XPath;
using HPCloud.Objects.DataAccess;

namespace HPCloud.Objects.Utility
{   
    public enum AvailabilityZone
    {      
      az1RegionAgeo1,
      az2RegionAgeo1,
      az3RegionAgeo1,
      az1RegionBgeo1  
    }

    public class Session
    {
        private BaseRepositoryFactory _factory;
        private Context _context;
        private AvailabilityZone _currentZone;

        #region Properties
//===============================================================================
/// <summary>
/// 
/// </summary>
//===============================================================================
        public Context Context
        {
            get { return _context; }
            set { _context = value; }
        }
//===============================================================================
/// <summary>
/// 
/// </summary>
/// <returns></returns>
//===============================================================================
        public BaseRepositoryFactory Factory
        {
            get { return _factory; }
            set { _factory = value; }
        }
        #endregion
        #region Methods
//===============================================================================
/// <summary>
/// 
/// </summary>
//===============================================================================
        private string TranslateZoneEnum(AvailabilityZone zone)
        {
            switch (zone)
            {
                case (AvailabilityZone.az1RegionAgeo1) : return "az-1.region-a.geo-1";
                case (AvailabilityZone.az1RegionBgeo1):  return "az-2.region-a.geo-1";
                case (AvailabilityZone.az2RegionAgeo1) : return "az-3.region-a.geo-1";
                case (AvailabilityZone.az3RegionAgeo1) : return "az-1.region-b.geo-1";
            }
            return null;
        }
//===============================================================================
/// <summary>
/// 
/// </summary>
//===============================================================================
        public void SetZone(AvailabilityZone zone)
        {
            _currentZone             = zone;
            string configFilePath    = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) + @"\" + @"HP\CLI.config";
            XDocument doc            = XDocument.Load(configFilePath);
            XElement zoneKeyNode     = doc.XPathSelectElement("//AvailabilityZone[@name='" + this.TranslateZoneEnum(_currentZone) + "']");
            XElement defaultZoneNode = doc.XPathSelectElement("//AvailabilityZone[@isDefault='True']");

            defaultZoneNode.SetAttributeValue("isDefault", "False");
            zoneKeyNode.SetAttributeValue("isDefault", "True");
            doc.Save(configFilePath);
        }
//=======================================================================================================
/// <summary>
/// 
/// </summary>
/// <returns></returns>
//=======================================================================================================
        private static bool DoesRequireCredentials(XElement accountIdNode, XElement accessKeyNode)
        {
            // First make sure the User info exist..

            System.Collections.Generic.IEnumerable<XAttribute> attributes = accountIdNode.Attributes();
            foreach (XAttribute attribute in attributes)
            {
                if (attribute.Name == "value" && attribute.Value == string.Empty)
                {
                    return true;
                }
            }

            // Now check to ensure the auth key exist

            System.Collections.Generic.IEnumerable<XAttribute> attributes2 = accessKeyNode.Attributes();
            foreach (XAttribute attribute in attributes2)
            {
                if (attribute.Name == "value" && attribute.Value == string.Empty)
                {
                    return true;
                }
            }

            return false;
        }
//===============================================================================
/// <summary>
/// 
/// </summary>
//===============================================================================
        private static AuthenticationRequest BuildAuthenticationRequest()
        {
            AuthenticationRequest request = new AuthenticationRequest();
            string configFilePath         = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) + @"\" + @"HP\CLI.config";
            XDocument doc                 = XDocument.Load(configFilePath);
            XElement accessKeyNode        = doc.XPathSelectElement("//add[@key='AccessKey']");
            XElement secretKeyNode        = doc.XPathSelectElement("//add[@key='SecretKey']");
            XElement tenantId             = doc.XPathSelectElement("//add[@key='DefaultTenantId']");

            if (DoesRequireCredentials(accessKeyNode, secretKeyNode))
            {
                throw new SecurityException("You must supply valid credentials to use this api. Please edit the CLI.config file and include your assigned credentials that you received via the online registration process.");
            }

            Credentials credentials = new Credentials();
            credentials.AccessKey   = Settings.Default.AccessKey;
            credentials.SecretKey   = Settings.Default.SecretKey;
            request.TenantId        = Settings.Default.DefaultTenantId;
            request.Credentials     = credentials;

            return request;
        }
//===============================================================================
/// <summary>
/// 
/// </summary>
/// <returns></returns>
//===============================================================================
        public static Session CreateSession(string accessKey, string secretKey, string tenantId)
        {
            Context context = new Context();
            Session session = new Session();

            AuthenticationRequest request     = new AuthenticationRequest();
            request.TenantId                  = tenantId;
            request.Credentials               = new Credentials(accessKey, secretKey);
            KeystoneAuthProvider authProvider = new KeystoneAuthProvider();
            AuthenticationResponse response   = authProvider.Authenticate(request);
            context.ServiceCatalog            = response.ServiceCatalog;
            context.Settings                  = Settings.Default;
            context.AccessToken               = response.Token;
            session.Factory                   = new BaseRepositoryFactory(context);
            session.Context                   = context;

            return session;
        }
//===============================================================================
/// <summary>
/// 
/// </summary>
/// <returns></returns>
//===============================================================================
        public static Session CreateSession()
        {
            Context context = new Context();
            Session session = new Session();

            AuthenticationRequest request = BuildAuthenticationRequest();

            if (request != null)
            {
                KeystoneAuthProvider authProvider = new KeystoneAuthProvider();
                AuthenticationResponse response   = authProvider.Authenticate(request);
                context.ServiceCatalog            = response.ServiceCatalog;
                context.Settings                  = Settings.Default;
                context.AccessToken               = response.Token;
                session.Factory                   = new BaseRepositoryFactory(context);
                session.Context                   = context;

                return session;
            }
            else
            {
                return null;
            }
        }
        #endregion
    }
}



